package com.sansan.qiangji.realize.system;

import com.sansan.qiangji.VO.system.menu.MenuPowerVO;
import com.sansan.qiangji.VO.system.menu.MenuVO;
import com.sansan.qiangji.entity.system.Menu;
import com.sansan.qiangji.entity.system.Role;
import com.sansan.qiangji.entity.system.User;
import com.sansan.qiangji.enums.ResultEnum;
import com.sansan.qiangji.exception.ServiceException;
import com.sansan.qiangji.form.system.menu.MenuAddForm;
import com.sansan.qiangji.service.impl.system.MenuServiceImpl;
import com.sansan.qiangji.service.impl.system.RoleServiceImpl;
import com.sansan.qiangji.service.impl.system.UserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MenuReal {
    private MenuServiceImpl menuService;
    private UserServiceImpl userService;
    private RoleServiceImpl roleService;

    @Resource
    public void setMenuService(MenuServiceImpl menuService) {
        this.menuService = menuService;
    }

    @Resource
    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    @Resource
    public void setRoleService(RoleServiceImpl roleService) {
        this.roleService = roleService;
    }

    @Transactional
    public void MenuCreate(MenuAddForm menuAddForm) {
        List<String> menuRootList = new ArrayList<>();
        menuRootList.add(menuAddForm.getMenuRoot());
        menuRootList.add(menuAddForm.getMenuNode());
        menuRootList.add((menuAddForm.getMenuParent()));
        List<Menu> menus = menuService.findByMenuRootIn(menuRootList);
        if (menus.stream().anyMatch(e -> e.getMenuRoot().equals(menuAddForm.getMenuRoot()))) {
            log.error("【创建菜单】菜单已存在，menuForm={}", menuAddForm.toString());
            throw new ServiceException(ResultEnum.MENU_EXIST);
        }
        if (menus.stream().noneMatch(e -> e.getMenuRoot().equals(menuAddForm.getMenuNode()))) {
            log.error("【创建菜单】根目录不存在，menuForm={}", menuAddForm.toString());
            throw new ServiceException(ResultEnum.MENU_ROOT_NOT_EXIST);
        }
        if (menus.stream().noneMatch(e -> e.getMenuRoot().equals(menuAddForm.getMenuParent()))) {
            log.error("【创建菜单】上级菜单不存在，menuForm={}", menuAddForm.toString());
            throw new ServiceException(ResultEnum.PARENT_MENU_NOT_EXIST);
        }
        //查找上级菜单的原下级菜单
        List<Menu> menuSons = menuService.findByMenuParent(menuAddForm.getMenuParent());
        menuSons = menuSons.stream().filter(e -> e.getMenuNode().equals(menuAddForm.getMenuNode())).collect(Collectors.toList());
        //添加新菜单
        Menu menu = new Menu();
        BeanUtils.copyProperties(menuAddForm, menu);
        menu.setMenuStatus(true);
        int rows = menuService.addMenu(menu);
        if (rows == 0) {
            log.error("【创建菜单】创建菜单失败，menuForm={}", menuAddForm.toString());
            throw new ServiceException(ResultEnum.CREATE_MENU_ERROR);
        }
        //修改原下级菜单
        if (menuSons.size() != 0) {
            menuSons.get(0).setMenuParent(menu.getMenuRoot());
            rows = menuService.updateMenu(menuSons.get(0));
            if (rows == 0) {
                log.error("【创建菜单】创建菜单失败，menuForm={}", menuAddForm.toString());
                throw new ServiceException(ResultEnum.CREATE_MENU_ERROR);
            }
        }
    }

    public MenuVO getMenus() {
        List<Menu> menus = menuService.findAllMenu();
        List<Menu> menuList = menus.stream().filter(e -> e.getMenuRoot().equals("root_menu")).collect(Collectors.toList());
        if (menuList.size() == 0) {
            log.error("【菜单列表】根目录不存在");
            throw new ServiceException(ResultEnum.MENU_ROOT_NOT_EXIST);
        }
        MenuVO menuVO = new MenuVO();
        BeanUtils.copyProperties(menuList.get(0), menuVO);
        List<MenuVO> menuVOS = menuService.getChildrenMenu(menus, "root_menu");
        if (menuVOS.size() != 0) {
            menuVO.setChildren(menuVOS);
        }
        return menuVO;
    }

    public MenuVO userMenuList() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        User user = userService.findByUserName(request.getAttribute("userName").toString());
        if (user == null){
            log.error("【用户菜单】根目录不存在");
            throw new ServiceException(ResultEnum.USER_NOT_EXIST);
        }
        List<Menu> menus = menuService.findAllMenu();
        List<Menu> menuList = menus.stream().filter(e -> e.getMenuRoot().equals("root_menu")).collect(Collectors.toList());
        if (menuList.size() == 0) {
            log.error("【用户菜单】根目录不存在");
            throw new ServiceException(ResultEnum.MENU_ROOT_NOT_EXIST);
        }
        MenuVO menuVO = new MenuVO();
        BeanUtils.copyProperties(menuList.get(0), menuVO);
        List<String> userMenus = new ArrayList<>();
        if (user.getUserMenus() != null) {
            userMenus = Arrays.asList(user.getUserMenus().split("\\|\\|"));
        }
        List<MenuVO> menuVOS = menuService.getUserChildrenMenu(menus, "root_menu", userMenus);
        if (menuVOS.size() != 0) {
            menuVO.setChildren(menuVOS);
        }
        return menuVO;
    }

    @Transactional
    public void changeMenuStatus(Integer menuId) {
        Menu menu = menuService.findByMenuId(menuId);
        if (menu == null) {
            log.error("【更改菜单状态】菜单不存在");
            throw new ServiceException(ResultEnum.MENU_NOT_EXIST);
        }
        menu.setMenuStatus(!menu.getMenuStatus());
        int rows = menuService.updateMenu(menu);
        if (rows == 0) {
            log.error("【更改菜单状态】更改菜单状态失败，menuId={}", menuId);
            throw new ServiceException(ResultEnum.CHANGE_USER_STATUS_ERROR);
        }
    }

    @Transactional
    public MenuVO editMenu(Integer menuId, String menuName, String menuPath) {
        Menu menu = menuService.findByMenuId(menuId);
        if (menu == null) {
            log.error("【编辑菜单】菜单不存在");
            throw new ServiceException(ResultEnum.MENU_NOT_EXIST);
        }
        menu.setMenuName(menuName);
        menu.setMenuPath(menuPath);
        int rows = menuService.updateMenu(menu);
        if (rows == 0) {
            log.error("【编辑菜单】编辑菜单失败，menuId={}", menuId);
            throw new ServiceException(ResultEnum.MENU_EDIT_ERROR);
        }
        MenuVO menuVO = new MenuVO();
        BeanUtils.copyProperties(menu, menuVO);
        return menuVO;
    }

    @Transactional
    public void deleteMenu(Integer menuId) {
        if (menuId == 1) {
            log.error("【删除菜单】根目录不可删除");
            throw new ServiceException(ResultEnum.ROOT_MENU_CAN_NOT_DELETE);
        }
        //判断菜单是否存在
        Menu menu = menuService.findByMenuId(menuId);
        if (menu == null) {
            log.error("【删除菜单】菜单不存在");
            throw new ServiceException(ResultEnum.MENU_NOT_EXIST);
        }
        //删除菜单及子菜单
        List<Menu> menus = menuService.findByMenuNode(menu.getMenuRoot());
        menus.add(menu);
        int rows = menuService.deleteByMenuId(menus);
        if (rows == 0) {
            log.error("【删除菜单】删除菜单失败，menuId={}", menuId);
            throw new ServiceException(ResultEnum.MENU_DELETE_ERROR);
        }
        //查询菜单的父菜单
        menus = menuService.findByMenuRoot(menu.getMenuParent());
        if (menus.size() == 0) {
            log.error("【删除菜单】找不到菜单的父菜单，menuId={}", menuId);
            throw new ServiceException(ResultEnum.MENU_PARENT_NOT_EXIT);
        }
        Menu menuParent = menus.get(0);
        //查询菜单的子菜单
        menus = menuService.findByMenuParent(menu.getMenuRoot());
        if (menus.size() != 0) {
            Menu menuSon = menus.get(0);
            menuSon.setMenuParent(menuParent.getMenuRoot());
            menuService.updateMenu(menuSon);
        }
    }

    @Transactional
    public MenuPowerVO userMenuPowerList(Integer userId) {
        List<Menu> menus = menuService.findAllMenu();
        List<Menu> menuList = menus.stream().filter(e -> e.getMenuRoot().equals("root_menu")).collect(Collectors.toList());
        if (menuList.size() == 0) {
            log.error("【用户菜单】根目录不存在");
            throw new ServiceException(ResultEnum.MENU_ROOT_NOT_EXIST);
        }
        User user = userService.findByUserId(userId);
        if (user == null) {
            log.error("【用户菜单】用户不存在");
            throw new ServiceException(ResultEnum.USER_NOT_EXIST);
        }
        MenuPowerVO menuPowerVO = new MenuPowerVO();
        BeanUtils.copyProperties(menuList.get(0), menuPowerVO);
        menuPowerVO.setIsEnable(true);
        List<String> menuPowers = new ArrayList<>();
        if (user.getUserMenus() != null) {
            menuPowers = Arrays.asList(user.getUserMenus().split("\\|\\|"));
        }
        List<MenuPowerVO> menuPowerVOS = menuService.getMenuChildrenPower(menus, "root_menu", menuPowers);
        if (menuPowerVOS.size() != 0) {
            menuPowerVO.setChildren(menuPowerVOS);
        }
        return menuPowerVO;
    }

    @Transactional
    public MenuPowerVO roleMenuPowerList(Integer roleId) {
        List<Menu> menus = menuService.findAllMenu();
        List<Menu> menuList = menus.stream().filter(e -> e.getMenuRoot().equals("root_menu")).collect(Collectors.toList());
        if (menuList.size() == 0) {
            log.error("【角色菜单】根目录不存在");
            throw new ServiceException(ResultEnum.MENU_ROOT_NOT_EXIST);
        }
        Role role = roleService.findByRoleId(roleId);
        if (role == null) {
            log.error("【角色菜单】角色不存在");
            throw new ServiceException(ResultEnum.ROLE_NOT_EXIST);
        }
        MenuPowerVO menuPowerVO = new MenuPowerVO();
        BeanUtils.copyProperties(menuList.get(0), menuPowerVO);
        menuPowerVO.setIsEnable(true);
        List<String> menuPowers = new ArrayList<>();
        if (role.getRoleMenus() != null) {
            menuPowers = Arrays.asList(role.getRoleMenus().split("\\|\\|"));
        }
        List<MenuPowerVO> menuPowerVOS = menuService.getMenuChildrenPower(menus, "root_menu", menuPowers);
        if (menuPowerVOS.size() != 0) {
            menuPowerVO.setChildren(menuPowerVOS);
        }
        return menuPowerVO;
    }

    @Transactional
    public void moveMenu(Integer menuId, String moveType){
        Menu menu = menuService.findByMenuId(menuId);
        if (menu == null) {
            log.error("【移动菜单】菜单不存在");
            throw new ServiceException(ResultEnum.MENU_NOT_EXIST);
        }
        if (!moveType.equals("up")&&!moveType.equals("down")){
            log.error("【移动菜单】菜单移动类型不存在");
            throw new ServiceException(ResultEnum.MENU_MOVE_TYPE_NOT_EXIST);
        }
        if (moveType.equals("up")){
            if (menu.getMenuNode().equals(menu.getMenuParent())){
                log.error("【移动菜单】菜单处于顶层不可上移");
                throw new ServiceException(ResultEnum.MENU_IS_UP_CAN_NOT_MOVE);
            }
            List<Menu> menuParents = menuService.findByMenuRoot(menu.getMenuParent());
            if (menuParents.size() == 0) {
                log.error("【移动菜单】找不到菜单的父菜单");
                throw new ServiceException(ResultEnum.MENU_PARENT_NOT_EXIT);
            }
            List<Menu> updateMenus = new ArrayList<>();
            List<Menu> menuSons = menuService.findByMenuNodeAndParent(menu.getMenuNode(), menu.getMenuRoot());
            menu.setMenuParent(menuParents.get(0).getMenuParent());
            menuParents.get(0).setMenuParent(menu.getMenuRoot());
            if (menuSons.size()!=0){
                menuSons.get(0).setMenuParent(menuParents.get(0).getMenuRoot());
                updateMenus.add(menuSons.get(0));
            }
            updateMenus.add(menuParents.get(0));
            updateMenus.add(menu);
            menuService.updateMenus(updateMenus);
        }
        if (moveType.equals("down")){
            List<Menu> menuSons = menuService.findByMenuNodeAndParent(menu.getMenuNode(), menu.getMenuRoot());
            if(menuSons.size() == 0){
                log.error("【移动菜单】菜单处于底层不可下移");
                throw new ServiceException(ResultEnum.MENU_IS_DOWN_CAN_NOT_MOVE);
            }
            List<Menu> updateMenus = new ArrayList<>();
            List<Menu> menuSonsSon = menuService.findByMenuNodeAndParent(menuSons.get(0).getMenuNode(), menuSons.get(0).getMenuRoot());
            menuSons.get(0).setMenuParent(menu.getMenuParent());
            menu.setMenuParent(menuSons.get(0).getMenuRoot());
            if (menuSonsSon.size()!=0){
                menuSonsSon.get(0).setMenuParent(menu.getMenuRoot());
                updateMenus.add(menuSonsSon.get(0));
            }
            updateMenus.add(menu);
            updateMenus.add(menuSons.get(0));
            menuService.updateMenus(updateMenus);
        }
    }
}
